package cz.muni.fi.pa165.web;

import cz.muni.fi.pa165.api.ForestService;
import cz.muni.fi.pa165.api.ForestVisitService;
import cz.muni.fi.pa165.api.dto.ForestDTO;
import cz.muni.fi.pa165.api.dto.ForestVisitDTO;
import cz.muni.fi.pa165.web.validation.ForestDTOEditValidator;
import cz.muni.fi.pa165.web.validation.ForestDTOValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 * Controller class for working with Forest
 *
 * @author Matej Cimbora
 */
@Controller
public class ForestController {

    @Autowired
    ForestService forestService;
    @Autowired
    ForestDTOValidator validator;
    @Autowired
    ForestDTOEditValidator editValidator;
    @Autowired
    ForestVisitService forestVisitService;

    @RequestMapping(value = "auth/forest")
    public String initial(ModelMap modelMap) {
        modelMap.addAttribute("command", new ForestDTO());
        modelMap.addAttribute("forests", forestService.retrieveAllForests());
        return "auth/forest";
    }

    @RequestMapping(value = "auth/removeForest*")
    public String removeAdmin(@RequestParam("id") String request, ModelMap modelMap) {
        ForestDTO forest = forestService.getForest(Long.valueOf(request));
        // remove forest visits for given forest
        for (ForestVisitDTO fv : forestVisitService.retrieveVisitsByForest(forest)) {
            forestVisitService.removeVisit(fv);
        }
        forestService.removeForest(forest);
        modelMap.addAttribute("command", new ForestDTO());
        modelMap.addAttribute("forests", forestService.retrieveAllForests());
        return "auth/forest";
    }

    @RequestMapping(value = "auth/editForest*")
    public String editAdmin(@RequestParam("id") String request, ModelMap model) {
        ForestDTO forest = forestService.getForest(Long.valueOf(request));
        model.addAttribute("command", forest);
        return "auth/editForest";
    }

    @RequestMapping(value = "auth/editedForest")
    public String editedForestAdmin(@ModelAttribute("command") ForestDTO forest,
            BindingResult result, ModelMap modelMap) {
        editValidator.validate(forest, result);
        if (result.hasErrors()) {
            modelMap.addAttribute("command", forest);
            return "auth/editForest";
        } else {
            forestService.updateForest(forest);
            modelMap.addAttribute("command", new ForestDTO());
            modelMap.addAttribute("forests", forestService.retrieveAllForests());
            return "auth/forest";
        }
    }

    @RequestMapping(value = "auth/addForest")
    public String add(@ModelAttribute("command") ForestDTO forest, BindingResult result, ModelMap modelMap) {
        validator.validate(forest, result);
        if (result.hasErrors()) {
            modelMap.addAttribute("forests", forestService.retrieveAllForests());
            return "auth/forest";
        } else {
            forestService.createForest(forest);
            modelMap.addAttribute("forests", forestService.retrieveAllForests());
            return "auth/forest";
        }
    }

    @ExceptionHandler(DataAccessException.class)
    public ModelAndView handleException(DataAccessException ex) {

        ModelAndView m = new ModelAndView();
        m.setViewName("forest");
        m.addObject("command", new ForestDTO());
        m.addObject("forests", forestService.retrieveAllForests());
        m.addObject("error", "Error has occured, try again");
        return m;
    }
}
